# 导入实体到 Neo4j
from src.database.connection import Neo4jInstance
from src.ifc.config import type_mapping
from py2neo import Node, Relationship

from src.ifc.load.span import calculate_span
from src.ifc.load.volume import calculate_volume
from src.util.applog import AppLog


# 清除数据库中原有的所有数据
def flush_neo4j():
    Neo4jInstance.get_connect().delete_all()
    AppLog.info("all nodes are deleted")


# def import_ifc_neo4j(ifc_file: ifcopenshell.file):
#    # 清除数据库中原有的所有数据
#    graph = Neo4jConnect.get_connect()
#    graph.delete_all()
#    logging.info('all nodes are deleted')
#
#    # 写入数据到 neo4j
#    write_data(ifc_file)


# 创建节点的方法(包含体积计算)
def create_node(entity):
    properties = {}
    for key, value in entity.get_info().items():
        if value is not None:
            properties[key] = (
                str(value) if not isinstance(value, (int, float, str, bool)) else value
            )

    volume = calculate_volume(entity)
    #    print('volume:', volume)
    properties["volume"] = volume

    # 梁和楼板的跨度
    if entity.is_a() == "IfcBeam" or entity.is_a() == "IfcSlab":
        properties["span"] = calculate_span(entity)

    # entity_type = entity.is_a()
    # label = type_mapping.get(entity_type, entity_type)  # 获取中文标签或默认实体类型名称
    return Node(entity.is_a(), **properties)


# 创建关系的方法
def create_relationship(start_node, end_node, rel_type):
    return Relationship(start_node, rel_type, end_node)


# 导入实体到 Neo4j
def import_entities(ifc_file):
    node_dict = {}  # 用于存储已创建的节点
    for ifc_type in type_mapping.keys():
        entities = ifc_file.by_type(ifc_type)
        tx = Neo4jInstance.get_connect().begin()
        for entity in entities:
            node = create_node(entity)
            node_dict[entity.GlobalId] = node
            tx.create(node)
        tx.commit()
    return node_dict


# 导入关系到 Neo4j
def import_relationships(ifc_file, node_dict, graph):
    # IfcRelAggregates：表示一个实体包含另一个实体，类似于 CONTAINS。
    rel_aggregates = ifc_file.by_type("IfcRelAggregates")
    for rel in rel_aggregates:
        start_node = node_dict.get(rel.RelatingObject.GlobalId)
        for related_object in rel.RelatedObjects:
            end_node = node_dict.get(related_object.GlobalId)
            if start_node and end_node:
                relationship = create_relationship(start_node, end_node, "CONTAINS")
                graph.create(relationship)

    # IfcRelConnectsElements：表示两个元素之间的连接关系，类似于 CONNECTED_TO。
    rel_connects = ifc_file.by_type("IfcRelConnectsElements")
    for rel in rel_connects:
        start_node = node_dict.get(rel.RelatingElement.GlobalId)
        end_node = node_dict.get(rel.RelatedElement.GlobalId)
        if start_node and end_node:
            relationship = create_relationship(start_node, end_node, "CONNECTED_TO")
            graph.create(relationship)

    # IfcRelContainedInSpatialStructure：表示一个元素包含在一个空间结构中，类似于 PLACED_IN。
    rel_contained = ifc_file.by_type("IfcRelContainedInSpatialStructure")
    for rel in rel_contained:
        end_node = node_dict.get(rel.RelatingStructure.GlobalId)
        for related_element in rel.RelatedElements:
            start_node = node_dict.get(related_element.GlobalId)
            if start_node and end_node:
                relationship = create_relationship(start_node, end_node, "PLACED_IN")
                graph.create(relationship)


# 导入实体和关系到 Neo4j
# node_dict = import_entities(ifc_file, graph)
# import_relationships(ifc_file, node_dict, graph)
